#!/bin/sh

# Author:       Bibby(michaelbibby@gmail.com)
# DATE:         2008.02.02
# Purpose:      Set up a mail server automaticly.

# Filename:     openbsd_mail_server.sh
# Version:      0.4

# DEBUG script.
#set -xv

ROOTDIR="$(pwd)"
CONFIG_DIR='conf'

# Global variables.
. ${ROOTDIR}/${CONFIG_DIR}/global

# Some useful functions.
. ${ROOTDIR}/${CONFIG_DIR}/functions

PORTS_LIST="${PORT_POSTFIX} ${PORT_FREEZE} ${PORT_UNRAR} ${PORT_UNARJ}"

# It will run '${ROOTDIR}/tools/${CONFIG_VIA_DIALOG}'.
check_env

# Application special.
# The order is important.
. ${ROOTDIR}/${CONFIG_DIR}/httpd
. ${ROOTDIR}/${CONFIG_DIR}/php
. ${ROOTDIR}/${CONFIG_DIR}/openldap
. ${ROOTDIR}/${CONFIG_DIR}/postfix
. ${ROOTDIR}/${CONFIG_DIR}/maildrop
. ${ROOTDIR}/${CONFIG_DIR}/courier
. ${ROOTDIR}/${CONFIG_DIR}/cyrus_sasl
. ${ROOTDIR}/${CONFIG_DIR}/squirrelmail
. ${ROOTDIR}/${CONFIG_DIR}/spamassassin
. ${ROOTDIR}/${CONFIG_DIR}/clamav
. ${ROOTDIR}/${CONFIG_DIR}/amavisd
. ${ROOTDIR}/${CONFIG_DIR}/spamd
. ${ROOTDIR}/${CONFIG_DIR}/mailgraph

. ${ROOTDIR}/${CONFIG_DIR}/misc

# ----------------------------------------------
# ---- For Apache and PHP(with extensions). ----
# ----------------------------------------------
config_httpd()
{
    perl -pi -e 's/(UseCanonicalName)(.*)(On)/${1}${2}Off/' ${HTTPD_CONF}
}

add_rc_entry_for_httpd()
{
    ECHO_INFO "Enable httpd. Add entry for httpd in ${RC_CONF_LOCAL}."
    echo "httpd_flags='${HTTPD_FLAGS}'" >>${RC_CONF_LOCAL}
}

start_httpd()
{
    ECHO_INFO "Starting httpd."
    apachectl stop
    apachectl start
}

install_php5_core()
{
    install_pkg php5-core ${PORT_PHP5_CORE}

    ECHO_INFO "Enable php module in httpd.conf."
    ${PHPXS} -s

    ECHO_INFO "Copy the sample configuration file."
    cp /usr/local/share/examples/php5/php.ini-recommended ${PHP_INI}

    ECHO_INFO "Modify httpd.conf for 'AddType'."
    perl -pi -e 's/^#(AddType\ application\/x-httpd-php)/$1/' ${HTTPD_CONF}

    ECHO_INFO "Modify httpd.conf for 'DirectoryIndex'."
    perl -pi -e 's/^(DirectoryIndex)/$1 index.php/' ${HTTPD_CONF}
}

install_php_extension()
{
    install_pkg php5-ldap ${PORT_PHP5_EXTENSIONS} ${PORT_PHP5_LDAP_BUILD}
    ${PHPXS} -a ldap

    install_pkg php5-imap ${PORT_PHP5_EXTENSIONS} ${PORT_PHP5_IMAP_BUILD}
    ${PHPXS} -a imap

    install_pkg php5-mhash ${PORT_PHP5_EXTENSIONS} ${PORT_PHP5_MHASH_BUILD}
    ${PHPXS} -a mhash
}

generate_php_info_page()
{
    ECHO_INFO "Generating php info page."
    cat >${HTTPD_DOCUMENTROOT}/index.php <<EOF
<?php
    phpinfo();
?>
EOF

    ECHO_INFO "Access URL to ensure PHP works with Apache via command:"
    ECHO_INFO "\tlynx 127.0.0.1"
}

# --------------------------------------------------
# ---- For OpenLDAP, LDAP schema(s), slapd.conf ----
# --------------------------------------------------
install_openldap_server()
{
    install_pkg ${PKG_OPENLDAP_SERVER} ${PORT_OPENLDAP} ${PORT_OPENLDAP_BUILD}
}

install_openldap_qmail_schema()
{
    ECHO_INFO "Copy qmail.schema -> /etc/openldap/schema/."
    cp tools/qmail.schema /etc/openldap/schema/
}

generate_slapd_conf()
{
    ECHO_INFO "Backup old ${OPENLDAP_SLAPD_CONF} to ${OPENLDAP_SLAPD_CONF}.${TIME}"
    cp ${OPENLDAP_SLAPD_CONF} ${OPENLDAP_SLAPD_CONF}.${TIME}

    ECHO_INFO "Generate new configuration file: ${OPENLDAP_SLAPD_CONF}."
    cat >${OPENLDAP_SLAPD_CONF} <<EOF
${CONF_MSG}
include     ${OPENLDAP_SCHEMA_DIR}/core.schema
include     ${OPENLDAP_SCHEMA_DIR}/corba.schema
include     ${OPENLDAP_SCHEMA_DIR}/cosine.schema
include     ${OPENLDAP_SCHEMA_DIR}/inetorgperson.schema
include     ${OPENLDAP_SCHEMA_DIR}/nis.schema

include     ${OPENLDAP_SCHEMA_DIR}/qmail.schema

pidfile     ${OPENLDAP_PID_DIR}/slapd.pid
argsfile    ${OPENLDAP_PID_DIR}/slapd.args

#
# Disallow bind as anonymous.
#
disallow    bind_anon

#
# Specify LDAP protocol version.
#require     LDAPv3
allow       bind_v2

# For debug
#loglevel   256
loglevel    0

#
# Access Control List. Used for LDAP bind.
#

#
# NOTE: Every domain have a administrator.
#   For domain: '${LDAP_YOUR_DOMAIN}'
#   Administrator:
#       mail=${LDAP_YOUR_DOMAIN_ADMIN_NAME}@${LDAP_YOUR_DOMAIN}, o=${LDAP_YOUR_DOMAIN}, ${LDAP_BASEDN}
#

#
# Set permission for LDAP attrs.
#
access to attrs="userPassword,mailForwardingAddress"
    by anonymous    auth
    by self         write
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=${LDAP_YOUR_DOMAIN_ADMIN_NAME}@([^,]+),o=\$1,${LDAP_BASEDN}"   write
    by users        none
access to attrs="cn,sn"
    by anonymous    auth
    by self         write
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=${LDAP_YOUR_DOMAIN_ADMIN_NAME}@([^,]+),o=\$1,${LDAP_BASEDN}"   write
    by users        read

access to attrs="destinationIndicator,mail,mailQuota,homeDirectory,mailMessageStore,mailForwardingAddress,accountStatus,objectclass"
    by anonymous    auth
    by self         read
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=${LDAP_YOUR_DOMAIN_ADMIN_NAME}@([^,]+),o=\$1,${LDAP_BASEDN}"    write
    by users        read

#
# Set ACL for vmail/vmailadmin.
#
access to dn="${LDAP_BINDDN}"
    by anonymous                    auth
    by self                         write
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by users                        none
access to dn="${LDAP_ADMIN_DN}"
    by anonymous                    auth
    by self                         write
    by users                        none

#
# Allow users to access their own domain subtree.
#
access to dn.regex="o=([^,]+),${LDAP_BASEDN}\$"
    by anonymous                    auth
    by self                         write
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=admin@\$1,o=\$1,${LDAP_BASEDN}\$" write
    by dn.regex="mail=[^,]+,o=\$1,${LDAP_BASEDN}\$" read
    by users                        none
#
# Enable vmail/vmailadmin. 
#
access to dn.subtree="${LDAP_BASEDN}"
    by anonymous                    auth
    by self                         write
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=${LDAP_YOUR_DOMAIN_ADMIN_NAME}@([^,]+),o=\$1,${LDAP_BASEDN}"    write
    by users                        read

#
# Set permission for "cn=*,${LDAP_SUFFIX}".
#
access to dn.regex="cn=[^,]+,${LDAP_SUFFIX}"
    by anonymous                    auth
    by self                         write
    by users                        none
#
# Set default permission.
#
access to *
    by anonymous                    auth
    by self                         write
    by users                        read

#######################################################################
# BDB database definitions
#######################################################################

database    ${LDAP_DATABASE}
suffix      "${LDAP_SUFFIX}"
directory   ${LDAP_DATA_DIR}

rootdn      "${LDAP_ROOTDN}"
rootpw      ${LDAP_ROOTPW}

#
# Set directory permission.
#
mode        0700

#
# Default index.
#
index       objectClass eq

#
# Index for mail attrs.
#
index       destinationIndicator,o   eq
index       homeDirectory,mailMessageStore,mail,mailForwardingAddress,accountStatus,cn eq
cachesize   1000
EOF
}

generate_ldap_conf()
{
    ECHO_INFO "Backup original LDAP client configuration file: ${OPENLDAP_LDAP_CONF}"
    cp ${OPENLDAP_LDAP_CONF} ${OPENLDAP_LDAP_CONF}.${TIME} 

    ECHO_INFO "Generating new LDAP client configuration file: ${OPENLDAP_LDAP_CONF}"
    cat >${OPENLDAP_LDAP_CONF} <<EOF
BASE    ${LDAP_SUFFIX}
URI     ldap://${LDAP_SERVER_HOST}:${LDAP_SERVER_PORT}
EOF
}

setting_openldap_log()
{
    ECHO_INFO "Setting up syslog configration file for openldap: /etc/syslog.conf"
    echo -e "local4.*\t\t\t\t\t\t${OPENLDAP_LOGFILE}" >>/etc/syslog.conf

    ECHO_INFO "Create log file for OpenLDAP: ${OPENLDAP_LOGFILE}."
    touch ${OPENLDAP_LOGFILE}

    ECHO_INFO "Setting logrotate for openldap."
    echo "${OPENLDAP_LOGFILE}   _openldap:_openldap 640 5   30  *   Z" >>/etc/newsyslog.conf

    ECHO_INFO "Restarting syslog: 'kill -HUP \$(cat /var/run/syslog.pid)'"
    kill -HUP $(cat /var/run/syslog.pid)
}

prepare_ldap_data_directory()
{
    ECHO_INFO "Create and configure directory for openldap pid/args file: ${OPENLDAP_PID_DIR}"
    mkdir -p ${OPENLDAP_PID_DIR}
    chown -R _openldap:_openldap ${OPENLDAP_PID_DIR}

    ECHO_INFO "Create instance directory for openldap tree: ${LDAP_DATA_DIR}."
    mkdir -p ${LDAP_DATA_DIR}
    chown -R _openldap:_openldap ${OPENLDAP_DATA_DIR}
    chmod -R 0700 ${OPENLDAP_DATA_DIR}

    ECHO_INFO "Generate DB_CONFIG for instance: ${LDAP_DATA_DIR}/DB_CONFIG."
    cp /usr/local/share/examples/openldap/DB_CONFIG ${LDAP_DATA_DIR}/DB_CONFIG
}

start_openldap()
{
    ECHO_INFO "Starting OpenLDAP."
    /usr/local/libexec/slapd ${OPENLDAP_FLAGS}
}

add_rc_entry_for_openldap()
{
    ECHO_INFO "Add RC entry for OpenLDAP."
    echo "openldap_flags='${OPENLDAP_FLAGS}'" >>${RC_CONF_LOCAL}

    cat >>${RC_LOCAL} <<EOF
# Start OpenLDAP daemon.
if [ X"\${openldap_flags}" != X"NO" ]; then
    echo -n ' openldap'
    mkdir /var/run/openldap
    chown -R _openldap:_openldap /var/run/openldap
    /usr/local/libexec/slapd \${openldap_flags}
fi
EOF
}

init_ldap_tree()
{
    ECHO_INFO "Initialization LDAP tree."
    ldapadd -x -D "${LDAP_ROOTDN}" -w "${LDAP_ROOTPW}" <<EOF
dn: ${LDAP_SUFFIX}
objectclass: dcObject
objectclass: organization
dc: ${LDAP_SUFFIX_MAJOR}
o: ${LDAP_SUFFIX_MAJOR}

dn: o=${LDAP_BASEDN_NAME},${LDAP_SUFFIX}
objectClass: Organization
o: ${LDAP_BASEDN_NAME}

dn: ${LDAP_BINDDN}
objectClass: person
objectClass: top
cn: ${VMAIL_USER_NAME}
sn: ${VMAIL_USER_NAME}
userPassword: ${LDAP_BINDPW}

dn: ${LDAP_ADMIN_DN}
objectClass: person
objectClass: top
cn: ${VMAIL_ADMIN_USER_NAME}
sn: ${VMAIL_ADMIN_USER_NAME}
userPassword: ${LDAP_ADMIN_PW}

dn: o=${LDAP_YOUR_DOMAIN},${LDAP_BASEDN}
objectClass: Organization
o: ${LDAP_YOUR_DOMAIN}
destinationIndicator: maildrop

dn: mail=${LDAP_EXAMPLE_USER}@${LDAP_YOUR_DOMAIN},o=${LDAP_YOUR_DOMAIN},${LDAP_BASEDN}
objectClass: inetOrgPerson
objectClass: qmailUser
objectClass: top
cn: ${LDAP_EXAMPLE_USER}
sn: ${LDAP_EXAMPLE_USER}
uid: ${LDAP_EXAMPLE_USER}
mail: ${LDAP_EXAMPLE_USER}@${LDAP_YOUR_DOMAIN}
accountStatus: active
homeDirectory: ${VMAIL_USER_HOME_DIR}
mailMessageStore: ${LDAP_YOUR_DOMAIN}/${LDAP_EXAMPLE_USER}/${MAILDIR_NAME}
mailQuota: 1024000S
userPassword: ${LDAP_EXAMPLE_USER_PASSWD}

dn: mail=${LDAP_YOUR_DOMAIN_ADMIN_NAME}@${LDAP_YOUR_DOMAIN},o=${LDAP_YOUR_DOMAIN},${LDAP_BASEDN}
objectClass: inetOrgPerson
objectClass: qmailUser
objectClass: top
cn: ${LDAP_YOUR_DOMAIN_ADMIN_NAME}
sn: ${LDAP_YOUR_DOMAIN_ADMIN_NAME}
uid: ${LDAP_YOUR_DOMAIN_ADMIN_NAME}
mail: ${LDAP_YOUR_DOMAIN_ADMIN_NAME}@${LDAP_YOUR_DOMAIN}
accountStatus: active
homeDirectory: ${VMAIL_USER_HOME_DIR}
mailMessageStore: ${LDAP_YOUR_DOMAIN}/${LDAP_YOUR_DOMAIN_ADMIN_NAME}/${MAILDIR_NAME}
mailQuota: 0S
userPassword: ${LDAP_YOUR_DOMAIN_ADMIN_PASSWD}
EOF
}

install_phpldapadmin()
{
    ECHO_INFO "Install phpldapadmin."
    install_pkg phpldapadmin ${PORT_PHPLDAPADMIN}

    ECHO_INFO "Create symbol link for phpldapadmin."
    cd ${HTTPD_DOCUMENTROOT}
    ln -s ../phpldapadmin-*/ phpldapadmin

    ECHO_INFO "Configure and set directory: ${HTTPD_SERVERROOT}/tmp/."
    mkdir -p ${HTTPD_SERVERROOT}/tmp
    chown www:daemon ${HTTPD_SERVERROOT}/tmp
    chmod 1755 ${HTTPD_SERVERROOT}/tmp
}

config_phpldapadmin()
{
    ECHO_INFO "Add phpLDAPadmin templates for create virtual domains/users."
    cp -f ${ROOTDIR}/tools/phpldapadmin/template/*xml ${HTTPD_DOCUMENTROOT}/phpldapadmin/templates/

    ECHO_INFO "You should click 'Purge Cache' link to enable these templates while you login into phpldapadmin."
}

# --------------------
# ---- Cyrus-SASL ----
# --------------------
install_cyrus_sasl_ldap()
{
    ECHO_INFO "Install package: ${PKG_CYRUS_SASL_LDAP}"
    pkg_add -r ${PKG_CYRUS_SASL_LDAP}

    rm -rf /var/sasl2/*
}

generate_smtpd_conf()
{
    ECHO_INFO "Generate smtpd.conf: ${SMTPD_CONF}."
    cat > ${SMTPD_CONF} <<EOF
${CONF_MSG}
pwcheck_method: saslauthd
mech_list: plain login
EOF
}

generate_saslauthd_conf()
{
    ECHO_INFO "Generate saslauthd.conf: ${SASLAUTHD_CONF}."
    cat > ${SASLAUTHD_CONF} <<EOF
${CONF_MSG}
ldap_servers: ldap://${LDAP_SERVER_HOST}:${LDAP_SERVER_PORT}/
ldap_search_base: ${LDAP_BASEDN}
ldap_timeout: 10
ldap_bind_dn: ${LDAP_BINDDN}
ldap_bind_pw: ${LDAP_BINDPW}
ldap_filter: (&(&(objectClass=qmailUser)(accountStatus=active))(mail=%u@%r))
EOF
}

add_rc_entry_for_saslauthd()
{
    ECHO_INFO "Add RC entry for saslauthd."
    echo "saslauthd_flags='${SASLAUTHD_FLAGS}'" >> ${RC_CONF_LOCAL}

    cat >>${RC_LOCAL} <<EOF
# Start the SASL2 auth daemon
if [ X"\${saslauthd_flags}" != X"NO" ] ; then
    echo -n ' saslauthd'
    mkdir -p /var/spool/postfix/var/sasl2 2>/dev/null
    /usr/local/sbin/saslauthd \${saslauthd_flags}
fi
EOF
}

# --------------------------------------------------
# ---- Postfix
# --------------------------------------------------
install_postfix()
{
    install_pkg pcre ${PORT_PCRE}
    install_pkg ${PKG_POSTFIX} ${PORT_POSTFIX} ${PORT_POSTFIX_BUILD}
}

enable_postfix()
{
    ECHO_INFO "Enable Postfix, replace sendmail."
    /usr/local/sbin/postfix-enable

    ECHO_INFO "Add RC entry for postfix: sendmail_flags."
    echo 'sendmail_flags="-bd"' >> ${RC_CONF_LOCAL}

    ECHO_INFO "Add flags to syslog."
    echo 'syslogd_flags="-a /var/spool/postfix/dev/log"' >> ${RC_CONF_LOCAL}

    ECHO_INFO "Disable crontab of sendmail. Required restart cron."
    perl -pi -e 's/^\*/#*/' /var/cron/tabs/root
}

basic_postfix_config()
{
    postconf -e myhostname=$(hostname)
    postconf -e mydomain=$(hostname)
    postconf -e myorigin=$(hostname)
    postconf -e inet_interfaces="all"
    postconf -e mynetworks="127.0.0.0/8"

    echo "root: ${MAIL_ALIAS_ROOT}" >> /etc/postfix/aliases
    postconf -e alias_maps="hash:/etc/postfix/aliases"
    postalias hash:/etc/postfix/aliases

    # We use 'maildir' format, not 'mbox'.
    postconf -e home_mailbox="Maildir/"

    # Set message_size_limit.
    postconf -e message_size_limit="${MESSAGE_SIZE_LIMIT}"
    postconf -e virtual_mailbox_limit_override="yes"

    # Set maildir overquota. 
    postconf -e virtual_overquota_bounce="yes"
    postconf -e virtual_maildir_limit_message="${MAILDIR_LIMIT_MESSAGE}"

    ECHO_INFO "Copy /etc/hosts to /var/spool/postfix/etc/."
    cp /etc/hosts /var/spool/postfix/etc/hosts

    ECHO_INFO "Generate file: ${MAIL_WHITELIST}."
    cat > ${MAIL_WHITELIST} <<EOF
${CONF_MSG}
#
# List the destination IP addresses here.
# 

127.0.0.1
EOF

    ECHO_INFO "Generate file: ${MAIL_BLACKLIST}."
    cat > ${MAIL_BLACKLIST} <<EOF
${CONF_MSG}
#
# List the destination IP addresses here.
# 

EOF

}

add_user_group_vmail()
{
    ECHO_INFO "Add virtual mail user/group: ${VMAIL_USER_NAME}."
    /usr/sbin/useradd -m -d ${VMAIL_USER_HOME_DIR} -s /sbin/nologin -u ${VMAIL_USER_UID} -g=uid ${VMAIL_USER_NAME}

    ECHO_INFO "Create directory(ies) for user(${VMAIL_USER_NAME}): ${VMAIL_USER_HOME_DIR}."
    mkdir -p ${VMAIL_USER_HOME_DIR}
    chown -R ${VMAIL_USER_UID}:${VMAIL_USER_GID} ${VMAIL_USER_HOME_DIR}

    ECHO_INFO "Delete dot files in HOME directory.\n\tUser: ${VMAIL_USER_NAME} \n\tHOME: ${VMAIL_USER_HOME_DIR}"
    rm -f ${VMAIL_USER_HOME_DIR}/.*
}

maildrop_config()
{
    install_pkg maildrop ${PORT_MAILDROP}

    ECHO_INFO "Generate configuration file: ${MAILDROPRC}."
    cat > ${MAILDROPRC} <<EOF
${CONF_MSG}
#
# logfile should be owned by user/group: vmail, mode: 0640.
# A newsyslog configuration was created for logrotate.
#
logfile "${MAILDROP_LOGFILE}"

VERBOSE     = "0"

SHELL       = "/bin/sh"
HOME        = "${VMAIL_USER_HOME_DIR}"
MAILDIR     = "${MAILDIR_NAME}"

LOGNAME     = tolower("\$LOGNAME")  # 'username@domain.com'
EXTENSION   = "\$1"                 # default is 'spam'
RECIPIENT   = tolower("\$2")
USER        = "\$3"                 # 'username'
HOST        = "\$4"                 # 'domain.com'
SENDER      = "\$5"

USERHOME    = "\$HOME/\$HOST/\$USER"
MAILBOX     = "\$HOME/\$HOST/\$USER/\$MAILDIR"

if ( \$EXTENSION = 'spam' )
{
    EXTENSION = 'Spam'
}

#
# \$HOME/.mailfilter
#   Owner UID/GID:  ${VMAIL_USER_UID}:${VMAIL_USER_GID}
#   Mode:   0600
#
\`test -r \$HOME/.mailfilter\`
if ( \$RETURNCODE == 0 )
{
    include \$HOME/.mailfilter
}

\`test -e \$MAILBOX\`
if ( \$RETURNCODE != 0 )
{
    # Create user home directory.
    \`mkdir -p \$USERHOME\`

    # Create Maildir.
    \`maildirmake \$MAILBOX && maildirmake -f \$EXTENSION \$MAILBOX \`

    # Auto-subscribe the subdirectory to imap server.
    \`print INBOX.Sent > \$MAILBOX/courierimapsubscribed\`
    \`print INBOX.Trash >> \$MAILBOX/courierimapsubscribed\`
    \`print INBOX.Drafts >> \$MAILBOX/courierimapsubscribed\`
    \`print INBOX.Spam >> \$MAILBOX/courierimapsubscribed\`

    # Set permission.
    \`chown ${VMAIL_USER_UID}:${VMAIL_USER_GID} -R \$MAILBOX \`
    \`chmod 0700 \$USERHOME\`
}

if (/^X-Spam-Flag:.*YES/)
{
    log "Spam detected. Move to the SPAM Folder: \$MAILBOX/.\$EXTENSION"
    exception {
        to \$MAILBOX/.\$EXTENSION/
    }
}
exception {
    to \$MAILBOX
}
EOF

    ECHO_INFO "Generate quota warnning message: /etc/quotawarnmsg."
    sed -e "s/Mailer-Daemon@example.com/root@$(hostname)/" \
        -e "s/support@example.com/root@$(hostname)/" /usr/local/share/doc/maildrop/quotawarnmsg > /etc/quotawarnmsg

    ECHO_INFO "Generate log file for maildrop: ${MAILDROP_LOGFILE}."
    touch ${MAILDROP_LOGFILE}
    chown ${VMAIL_USER_UID}:${VMAIL_USER_GID} ${MAILDROP_LOGFILE}
    chmod 644 ${MAILDROP_LOGFILE}

    ECHO_INFO "Setting logrotate for maildrop."
    echo "${MAILDROP_LOGFILE}   ${VMAIL_USER_NAME}:${VMAIL_USER_NAME}   640 5   30  *   Z" >>/etc/newsyslog.conf

    ECHO_INFO "Enable maildrop in postfix."
    ECHO_INFO "/etc/postfix/main.cf"
    postconf -e virtual_transport='maildrop'
    postconf -e maildrop_destination_concurrency_limit='2'
    postconf -e maildrop_destination_recipient_limit='1'

    ECHO_INFO "Backup file: ${POSTFIX_FILE_MASTER_CF} -> ${POSTFIX_FILE_MASTER_CF}.${TIME}"
    cp ${POSTFIX_FILE_MASTER_CF} ${POSTFIX_FILE_MASTER_CF}.${TIME}

    perl -pi -e 's/^#(maildrop)/$1/' ${POSTFIX_FILE_MASTER_CF}
    perl -pi -e 's/^#(.*user=vmail)(.*) -d.*/${1}:vmail${2} -w 90 -d \${user}\@\${nexthop} \${extension} \${recipient} \${user} \${nexthop} \${sender}/' ${POSTFIX_FILE_MASTER_CF}
}

ldap_config_for_postfix()
{
    ECHO_INFO "Setting up LDAP configuration for Postfix."
    #
    # Configure mydestination to hold virtual domains.
    ECHO_INFO "Setting up 'mydestination'."
    #postconf -e mydestination='$myhostname, localhost, localhost.$myhostname, ldap:virtualdomains'

    ldap_virtual_domains="${POSTFIX_ROOTDIR}/ldap_virtual_domains.cf"
    postconf -e mydestination="\$myhostname, localhost, localhost.\$myhostname, ldap:${ldap_virtual_domains}"

    #
    # For mydestination = ldap:virtualdomains
    #
    ECHO_INFO "Setting up LDAP virtual domains: ldap:virtualdomains."

    cat >${ldap_virtual_domains} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
bind            = ${LDAP_BIND}
start_tls       = no
version         = ${LDAP_BIND_VERSION}
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = ${LDAP_BASEDN}
scope           = one
query_filter    = (o=%s)
result_attribute= o
debug_level     = 0
EOF

    #postconf -e relay_domains="\$mydestination"

    #
    # LDAP transport maps
    #
    ECHO_INFO "Setting up LDAP transport_maps: ldap:ldaptransport."

    #postconf -e transport_maps="ldap:ldaptransport"

    ldap_transport_maps="${POSTFIX_ROOTDIR}/ldap_transport_maps.cf"
    postconf -e transport_maps="ldap:${ldap_transport_maps}"

    cat > ${ldap_transport_maps} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
version         = ${LDAP_BIND_VERSION}
bind            = ${LDAP_BIND}
start_tls       = no
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = ${LDAP_BASEDN}
scope           = one
query_filter    = (o=%s)
result_attribute= destinationIndicator
debug_level     = 0
EOF

    #
    # LDAP Virtual Users.
    #
    ECHO_INFO "Setting up LDAP virtual users."

    postconf -e virtual_minimum_uid="${VMAIL_USER_UID}"
    postconf -e virtual_uid_maps="static:${VMAIL_USER_UID}"
    postconf -e virtual_gid_maps="static:${VMAIL_USER_GID}"

    postconf -e virtual_mailbox_base="${VMAIL_USER_HOME_DIR}"

    #postconf -e virtual_mailbox_maps='ldap:accounts'
    ldap_accounts="${POSTFIX_ROOTDIR}/ldap_accounts.cf"
    ldap_accountsmap="${POSTFIX_ROOTDIR}/ldap_accountsmap.cf"

    postconf -e virtual_mailbox_maps="ldap:${ldap_accounts}, ldap:${ldap_accountsmap}"

    cat > ${ldap_accounts} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
version         = ${LDAP_BIND_VERSION}
bind            = ${LDAP_BIND}
start_tls       = no
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = o=%d,${LDAP_BASEDN}
scope           = one
query_filter    = (&(&(mail=%s)(objectClass=qmailUser))(accountStatus=active))
result_attribute= mailMessageStore
debug_level     = 0
EOF

    cat > ${ldap_accountsmap} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
version         = ${LDAP_BIND_VERSION}
bind            = ${LDAP_BIND}
start_tls       = no
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = o=%d,${LDAP_BASEDN}
scope           = one
query_filter    = (&(&(mail=%s)(objectClass=qmailUser))(accountStatus=active))
result_attribute= mail
debug_level     = 0
EOF

    ldap_alias_maps="${POSTFIX_ROOTDIR}/ldap_alias_maps.cf"
    postconf -e virtual_alias_maps="ldap:${ldap_alias_maps}"

    cat > ${ldap_alias_maps} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
version         = ${LDAP_BIND_VERSION}
bind            = ${LDAP_BIND}
start_tls       = no
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = o=%d,${LDAP_BASEDN}
scope           = one
query_filter    = (&(&(mail=%s)(objectClass=qmailUser))(accountStatus=active))
result_attribute= mailForwardingAddress
debug_level     = 0
EOF

    postconf -e local_recipient_maps='$alias_maps $virtual_mailbox_maps'
}

sasl_config_for_postfix()
{
    ECHO_INFO "Setting up SASL configration for Postfix."
    #
    # For SASL auth
    #
    postconf -e smtpd_sasl_auth_enable="yes"
    postconf -e smtpd_sasl_local_domain=''
    postconf -e smtpd_sasl_security_options="noanonymous"
    postconf -e broken_sasl_auth_clients="yes"
    postconf -e smtpd_recipient_restrictions="permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination"
    #   reject_non_fqdn_hostname,
    #   reject_non_fqdn_sender,
    #   reject_non_fqdn_recipient,
    #   reject_unauth_pipelining,
    #   reject_invalid_hostname,
}

# --------------------------------------------------
# ---- Courier POP3/IMAP.
# --------------------------------------------------
install_courier_authlib_ldap()
{
    install_pkg courier-authlib-ldap \
    ${PORT_COURIER_AUTHLIB_LDAP} \
    ${PORT_COURIER_AUTHLIB_LDAP_BUILD}
}

add_rc_entry_for_authdaemon()
{
    ECHO_INFO "Add rc entry for authdaemon."
    echo "authdaemond_flags='${AUTHDAEMOND_FLAGS}'" >>${RC_CONF_LOCAL}

    cat >>${RC_LOCAL} <<EOF
# Start courier-authlib authdaemond.
if [ X"\${authdaemond_flags}" != X"NO" ]; then
    echo -n ' authdaemond'
    mkdir /var/run/courier-auth 2>/dev/null
    /usr/local/sbin/authdaemond start
fi
EOF
}

ldap_config_for_courier_authlib_authdaemonrc()
{
    ECHO_INFO "Setting up LDAP configuration for courier-authlib-ldap: ${AUTHDAEMONRC}."
    perl -pi -e 's/(authmodulelist=")authuserdb authpwd authpgsql (authldap) authmysql authpipe(")/$1$2$3/' ${AUTHDAEMONRC}
    perl -pi -e 's/(authmodulelistorig=")authuserdb authpwd authpgsql (authldap) authmysql authpipe(")/$1$2$3/' ${AUTHDAEMONRC}
}

ldap_config_for_courier_authlib_authldaprc()
{
    ECHO_INFO "Setting up LDAP configuration for courier-authlib-ldap: ${AUTHLDAPRC}."

    ECHO_INFO "Backup old configuration file: ${AUTHLDAPRC}."
    cp "${AUTHLDAPRC}" "${AUTHLDAPRC}.${TIME}"

    ECHO_INFO "Generate new configuration file."
    cat >${AUTHLDAPRC} <<EOF
${CONF_MSG}
LDAP_URI                ldap://${LDAP_SERVER_HOST}:${LDAP_SERVER_PORT}
LDAP_BASEDN             ${LDAP_BASEDN}
LDAP_BINDDN             ${LDAP_BINDDN}
LDAP_BINDPW             ${LDAP_BINDPW}
LDAP_TIMEOUT            5
LDAP_AUTHBIND           1
#LDAP_FILTER             (objectClass=CourierMailAccount)
LDAP_FILTER             (&(objectClass=qmailUser)(accountStatus=active))
LDAP_GLOB_UID           ${VMAIL_USER_UID}
LDAP_GLOB_GID           ${VMAIL_USER_GID}
LDAP_HOMEDIR            homeDirectory
LDAP_MAILDIR            mailMessageStore
LDAP_MAILDIRQUOTA       mailQuota
LDAP_DEFAULTDELIVERY    defaultDelivery
LDAP_FULLNAME           cn
#LDAP_CLEARPW            clearPassword
LDAP_CRYPTPW            userPassword
LDAP_DEREF              never
LDAP_TLS                0
EOF
}

install_courier_pop3()
{
    install_pkg courier-pop3 ${PORT_COURIER_POP3} ${PORT_COURIER_POP3_BUILD}
}

add_rc_entry_for_courier_pop3()
{
    ECHO_INFO "Add rc entry for courier-pop3."
    echo "pop3d_flags='${POP3D_FLAGS}'" >>${RC_CONF_LOCAL}

    cat >>${RC_LOCAL} <<EOF
# Start the Courier POP3 daemon
if [ X"\${pop3d_flags}" != X"NO" ]; then
    echo -n ' pop3d'
    mkdir /var/run/courier 2>/dev/null
    /usr/local/libexec/pop3d.rc start
fi
EOF
}

install_courier_imap()
{
    install_pkg courier-imap ${PORT_COURIER_IMAP} ${PORT_COURIER_IMAP_BUILD}
}

create_user_maildir()
{
    user_home="${VMAIL_USER_HOME_DIR}/${LDAP_YOUR_DOMAIN}/${LDAP_EXAMPLE_USER}"
    user_maildir="${user_home}/${MAILDIR_NAME}"

    ECHO_INFO "Create and set maildir folder for LDAP_EXAMPLE_USER: ${LDAP_EXAMPLE_USER}."

    mkdir -p ${user_home}
    maildirmake ${user_maildir}
    maildirmake -f Spam ${user_maildir}

    print INBOX.Sent > ${user_maildir}/courierimapsubscribed
    print INBOX.Trash >> ${user_maildir}/courierimapsubscribed
    print INBOX.Drafts >> ${user_maildir}/courierimapsubscribed
    print INBOX.Spam >> ${user_maildir}/courierimapsubscribed

    chown -R ${VMAIL_USER_UID}:${VMAIL_USER_GID} ${VMAIL_USER_HOME_DIR}/${LDAP_YOUR_DOMAIN}/
    chmod -R 0700 ${VMAIL_USER_HOME_DIR}/${LDAP_YOUR_DOMAIN}/
}

add_rc_entry_for_courier_imap()
{
    ECHO_INFO "Add rc entry for courier-imap."
    echo "imapd_flags='${IMAPD_FLAGS}'" >>${RC_CONF_LOCAL}

    cat >>${RC_LOCAL} <<EOF
# Start the Courier IMAP daemon
if [ X"\${imapd_flags}" != X"NO" ]; then
    echo -n ' imapd'
    mkdir /var/run/courier 2>/dev/null
    /usr/local/libexec/imapd.rc start
fi
EOF
}

# --------------------------------------------------
# ---- SquirrelMail
# --------------------------------------------------

enable_squirrelmail_plugins()
{
    # We do *NOT* use 'conf.pl' to enable plugins, because it's not easy to
    # control in non-interactive mode, so we use 'perl' to modify the config
    # file directly.

    ECHO_INFO "Enable SquirrelMail plugins: ${ENABLED_PLUGINS}"
    
    # Disable all exist plugins first.
    perl -pi -e 's/^(\$plugins*)/\/\/$1/' ${SQUIRRELMAIL_CONFIG}

    if [ X"$#" != X"0" ]; then
        counter=0

        while [ ${counter} -lt $# ]; do
            plugin_name="\$$((counter+1))"
            echo "\$plugins[${counter}]='$(eval echo ${plugin_name})';" >> ${SQUIRRELMAIL_CONFIG}
            counter=$((counter+1))
        done
    else
        echo "Usage: enable_plugins plugin1 [plugin2 plugin3 ...]"
    fi
}

prepare_env_for_squirrelmail()
{
    cd ${MISC_PATH}

    # Extract source tarball.
    extract_pkg ${SQUIRRELMAIL_TARBALL}

    ECHO_INFO "Move squirrelmail to httpd SERVERROOT: ${SQUIRRELMAIL_HTTPD_ROOT}."
    mv squirrelmail-${SQUIRRELMAIL_VERSION} ${SQUIRRELMAIL_HTTPD_ROOT}

    ECHO_INFO "Set correct permission for squirrelmail: ${SQUIRRELMAIL_HTTPD_ROOT}."
    chown -R www:www ${SQUIRRELMAIL_HTTPD_ROOT}

    ECHO_INFO "Create symbol link for squirrelmail: ${HTTPD_DOCUMENTROOT}/mail/."
    cd ${HTTPD_DOCUMENTROOT}
    ln -s ../squirrelmail-${SQUIRRELMAIL_VERSION} mail

    ECHO_INFO "Create and set directory(ies) to storage squirrelmail data and attachments:"
    ECHO_INFO "\t${SQUIRRELMAIL_HTTPD_ROOT}/data/"
    ECHO_INFO "\t${SQUIRRELMAIL_HTTPD_ROOT}/attach/"

    cd ${SQUIRRELMAIL_HTTPD_ROOT}
    mkdir data attach
    chown www:www data attach
    chmod 730 attach

    ECHO_INFO "Access the webmail from URL: http://${hostname}/mail/"
}

config_squirrelmail()
{
    ECHO_INFO "Setting up configuration file for SquirrelMail."
    ${SQUIRRELMAIL_CONF_PL} <<EOF
2
1
$(hostname)
A
4
127.0.0.1
B
4
127.0.0.1
R
4
1
/squirrelmail-${SQUIRRELMAIL_VERSION}/data/
2
/squirrelmail-${SQUIRRELMAIL_VERSION}/attach/
R
6
1
+
127.0.0.1
${LDAP_BASEDN}
389
utf-8
Global LDAP Address Book

${LDAP_BINDDN}
${LDAP_BINDPW}
3
d
R
10
1
${SQUIRRELMAIL_DEFAULT_LOCALE}
2
${SQUIRRELMAIL_DEFAULT_CHARSET}
R
D
courier

S

Q
EOF
}

#
# For squirrelmail plugin: change_ldappass.
#

prepare_env_for_squirrelmail_plugin_change_ldappass()
{
    cd ${MISC_PATH}
    extract_pkg ${PLUGIN_CHANGE_LDAPPASS_TARBALL}

    ECHO_INFO "Move plugin to: ${SQUIRRELMAIL_PLUGIN_DIR}."
    mv change_ldappass ${SQUIRRELMAIL_PLUGIN_DIR}
    chown -R www:www ${SQUIRRELMAIL_PLUGIN_DIR}
    chmod -R 0755 ${SQUIRRELMAIL_PLUGIN_DIR}
}

config_squirrelmail_plugin_change_ldappass()
{
    cd ${SQUIRRELMAIL_PLUGIN_DIR}/change_ldappass/

    ECHO_INFO "Generate configration file: ${SQUIRRELMAIL_PLUGIN_DIR}/change_ldappass/config.php."
    cat >${PLUGIN_CHANGE_LDAPPASS_CONFIG} <<EOF
<?php
${CONF_MSG}
\$ldap_server = 'ldap://${LDAP_SERVER_HOST}:${LDAP_SERVER_PORT}';
\$ldap_protocol_version = ${LDAP_BIND_VERSION};
\$ldap_password_field = 'userPassword';
\$ldap_user_field = 'mail';
\$ldap_base_dn = '${LDAP_BASEDN}';
\$ldap_filter = '(&(objectClass=qmailUser)(accountStatus=active))';
\$query_dn="${LDAP_BINDDN}";
\$query_pw="${LDAP_BINDPW}";
\$ldap_bind_as_manager = false;
\$ldap_bind_as_manager = false;
\$ldap_manager_dn='';
\$ldap_manager_pw='';
\$change_smb=false;
\$debug=false;
EOF

    chown www:www ${PLUGIN_CHANGE_LDAPPASS_CONFIG}
    chmod 644 ${PLUGIN_CHANGE_LDAPPASS_CONFIG}
}

#
# For squirrelmail plugin: change_ldappass.
#

prepare_env_for_squirrelmail_plugin_compatibility()
{
    cd ${MISC_PATH}
    extract_pkg ${PLUGIN_COMPATIBILITY_TARBALL}

    ECHO_INFO "Move plugin to: ${SQUIRRELMAIL_PLUGIN_DIR}."
    mv compatibility ${SQUIRRELMAIL_PLUGIN_DIR}
    chown -R www:www ${SQUIRRELMAIL_PLUGIN_DIR}/compatibility/
    chmod -R 0755 ${SQUIRRELMAIL_PLUGIN_DIR}/compatibility/
}

#
# For squirrelmail plugin: Check Quota.
#

prepare_env_for_squirrelmail_plugin_check_quota()
{
    cd ${MISC_PATH}
    extract_pkg ${PLUGIN_CHECK_QUOTA_TARBALL}

    ECHO_INFO "Move plugin to: ${SQUIRRELMAIL_PLUGIN_DIR}."
    mv check_quota ${SQUIRRELMAIL_PLUGIN_DIR}
    chown -R www:www ${SQUIRRELMAIL_PLUGIN_DIR}/check_quota/
    chmod -R 0755 ${SQUIRRELMAIL_PLUGIN_DIR}/check_quota/
}

config_squirrelmail_plugin_check_quota()
{
    ECHO_INFO "Generate configuration file for plugin: check_quota."
    cp ${SQUIRRELMAIL_PLUGIN_DIR}/check_quota/config.sample.php ${SQUIRRELMAIL_PLUGIN_DIR}/check_quota/config.php
    chown -R www:www ${SQUIRRELMAIL_PLUGIN_DIR}/check_quota/config.php
    chmod -R 0755 ${SQUIRRELMAIL_PLUGIN_DIR}/check_quota/config.php

    ECHO_INFO "Configure plugin: check_quota."
    perl -pi -e 's/(.*)(quota_type)(.*)0;/${1}${2}${3}1;/' ${SQUIRRELMAIL_PLUGIN_DIR}/check_quota/config.php
}

#
# For SquirrelMail plugin: select_language.
#

prepare_env_for_squirrelmail_plugin_select_language()
{
    ECHO_INFO "Prepare plugin: select language."

    cd ${MISC_PATH}
    extract_pkg ${PLUGIN_SELECT_LANGUAGE_TARBALL}

    mv select_language ${SQUIRRELMAIL_PLUGIN_DIR}
    chown -R www:www ${SQUIRRELMAIL_PLUGIN_DIR}/select_language
    chmod -R 755 ${SQUIRRELMAIL_PLUGIN_DIR}/select_language
}

#
# For SquirrelMail translations.
#

config_squirrelmail_translations()
{
    cd ${MISC_PATH}

    extract_pkg ${SQUIRRELMAIL_TRANSLATIONS_TARBALL} /tmp
    
    ECHO_INFO "Copy SquirrelMail translations to ${SQUIRRELMAIL_HTTPD_ROOT}/"
    cp -rf /tmp/locale/* ${SQUIRRELMAIL_HTTPD_ROOT}/locale/
    cp -rf /tmp/images/* ${SQUIRRELMAIL_HTTPD_ROOT}/images/
    cp -rf /tmp/help/* ${SQUIRRELMAIL_HTTPD_ROOT}/help/
}

convert_translation_locale()
{
    # convert_locale zh_CN zh_CN.GB2312 zh_CN.UTF8 gb2312 utf-8
    #                $1    $2           $3         $4     $5
    export language="$1"
    export locale_old="$2"
    export locale_new="$3"
    export charset_old="$4"
    export charset_new="$5"

    ECHO_INFO "Convert translation locale: $language"
    ECHO_INFO "LOCALE: $2 -> $3. CHARSET: $4 -> $5."

    if [ -d ${SQUIRRELMAIL_HTTPD_ROOT}/locale/${language}/ ]; then
        cd ${SQUIRRELMAIL_HTTPD_ROOT}/locale/${language}/LC_MESSAGES/
        cp squirrelmail.po squirrelmail.po.${charset_old}
        iconv -f ${charset_old} -t ${charset_new} squirrelmail.po.${charset_old} > squirrelmail.po

        cd ${SQUIRRELMAIL_HTTPD_ROOT}/locale/${language}/
        cp setup.php setup.php.bak
        perl -pi -e 's/(.*)$ENV{"charset_old"}(.*)/$1$ENV{"charset_new"}$2/' setup.php
        perl -pi -e 's/(.*)$ENV{"locale_old"}(.*)/$1$ENV{"locale_new"}$2/' setup.php
    fi

    if [ -d ${SQUIRRELMAIL_HTTPD_ROOT}/help/${language} ]; then

        cd ${SQUIRRELMAIL_HTTPD_ROOT}/help/${language}

        for i in $(ls *); do
            cp $i $i.bak
            iconv -f ${charset_old} -t ${charset_new} $i.bak >$i
        done
    fi

    cd ${SQUIRRELMAIL_HTTPD_ROOT}/functions/
    cp i18n.php i18n.php.bak
    perl -pi -e 's/(.*)$ENV{"charset_old"}(.*)/$1$ENV{"charset_new"}$2/' i18n.php
    perl -pi -e 's/(.*)$ENV{"locale_old"}(.*)/$1$ENV{"locale_new"}$2/' i18n.php
}

# ----------------------------------------------
# For SpamAssassin
# ----------------------------------------------
install_spamassassin()
{
    install_pkg p5-Mail-SpamAssassin ${PORT_SPAMASSASSIN}
}

config_spamassassin()
{
    ECHO_INFO "Backup old configration file: ${SPAMASSASSIN_LOCAL_CF}."
    cp ${SPAMASSASSIN_LOCAL_CF} ${SPAMASSASSIN_LOCAL_CF}.${TIME}

    ECHO_INFO "Generate new configuration file: ${SPAMASSASSIN_LOCAL_CF}."
    cat >${SPAMASSASSIN_LOCAL_CF} <<EOF
${CONF_MSG}
# See also:
#    $ man Mail::SpamAssassin::Conf
#
rewrite_header      Subject [SPAM]
report_safe         0
lock_method         flock
required_score      5.0

use_bayes          1
auto_learn         1

#
# Whitelist.
#

whitelist_from      *@gmail.com
whitelist_from      *@sina.com *@sina.com.cn
whitelist_from      *@yahoo.com *@yahoo.com.cn
whitelist_from      *@163.com

#
# Blacklist.
#

#blacklist_from     *@abc.com *@123.com

EOF
}

# ----------------------------------------------
# For ClamAV
# ----------------------------------------------
install_unrar_unarj()
{
    install_pkg unrar ${PORT_UNRAR}
    install_pkg unarj ${PORT_UNARJ}
}

install_clamav()
{
    install_pkg clamav ${PORT_CLAMAV}
}

config_clamav_freshclam()
{
    ECHO_INFO "Configure freshclam."
    perl -pi -e 's/^(Example)/#$1/' ${FRESHCLAM_CONF}
    perl -pi -e 's/^(DatabaseMirror)/$1/' ${FRESHCLAM_CONF}

    cat >> ${FRESHCLAM_CONF} <<EOF
DatabaseDirectory /var/db/clamav
UpdateLogFile ${FRESHCLAM_LOGFILE}
LogVerbose yes
LogFileMaxSize 10M
PidFile ${CLAMAV_PID_DIR}/freshclam.pid
DatabaseOwner _clamav
#
# You can choose your nearest mirror from:
#   http://www.clamav.net/mirrors.html
#
DatabaseMirror clamav.cs.pu.edu.tw
#DatabaseMirror database.clamav.net
#DatabaseMirror db.cn.clamav.net
EOF

    ECHO_INFO "Create directory for clamav to store pidfile: ${CLAMAV_PID_DIR}."
    mkdir ${CLAMAV_PID_DIR}
    chown -R _clamav:_clamav ${CLAMAV_PID_DIR}

    ECHO_INFO "Generate log file for freshclam: ${FRESHCLAM_LOGFILE}."
    touch ${FRESHCLAM_LOGFILE}
    chown _clamav:_clamav ${FRESHCLAM_LOGFILE}

    ECHO_INFO "Setting logrotate for freshclam."
    echo "${FRESHCLAM_LOGFILE}   _clamav:_clamav    640 5   30  *   Z" >>/etc/newsyslog.conf
}

add_rc_entry_for_freshclam()
{
    ECHO_INFO "Add RC entry for freshclam."
    echo "freshclam_flags='-d -c 2'" >> ${RC_CONF_LOCAL}

    cat >> ${RC_LOCAL} <<EOF
# Start freshclam.
if [ X"\${freshclam_flags}" != X"NO" ]; then
    echo -n ' freshclam'
    mkdir ${CLAMAV_PID_DIR} 2>/dev/null
    chown -R _clamav:_clamav ${CLAMAV_PID_DIR}
    /usr/local/bin/freshclam \${freshclam_flags}
fi
EOF
}

config_clamav_clamd()
{
    ECHO_INFO "Configure clamd: ${CLAMD_CONF}."
    perl -pi -e 's/^(Example)/#$1/' ${CLAMD_CONF}

    cat >> ${CLAMD_CONF} <<EOF
#
# Log file.
#
LogFile ${CLAMD_LOGFILE}
LogFileMaxSize 2M
LogTime yes
LogVerbose yes

PidFile ${CLAMAV_PID_DIR}/clamd.pid
TemporaryDirectory /var/tmp
DatabaseDirectory /var/db/clamav
LocalSocket /var/run/clamav/clamd
User _clamav
EOF

    ECHO_INFO "Create directory for clamav to store pidfile: ${CLAMAV_PID_DIR}."
    mkdir ${CLAMAV_PID_DIR} 2>/dev/null
    chown -R _clamav:_clamav ${CLAMAV_PID_DIR}

    # Generate log file.
    touch ${CLAMD_LOGFILE}
    chown _clamav:_clamav ${CLAMD_LOGFILE}

    ECHO_INFO "Setting logrotate for clamd."
    echo "${CLAMD_LOGFILE}   _clamav:_clamav    640 5   30  *   Z" >>/etc/newsyslog.conf
}

add_rc_entry_for_clamd()
{
    ECHO_INFO "Add RC entry for clamd."
    echo "clamd_flags=''" >> ${RC_CONF_LOCAL}

    cat >> ${RC_LOCAL} <<EOF
# Start clamd.
if [ X"\${clamd_flags}" != X"NO" ]; then
    echo -n ' clamd'
    mkdir ${CLAMAV_PID_DIR} 2>/dev/null
    chown -R _clamav:_clamav ${CLAMAV_PID_DIR}
    /usr/local/sbin/clamd \${clamd_flags} >/dev/null 2>&1
fi
EOF
}

# --------------------------------------------------
# For amavisd-new
# --------------------------------------------------
install_amavisd()
{
    install_pkg freeze ${PORT_FREEZE}   # install freeze as dependence.
    install_pkg amavisd-new ${PORT_AMAVISD}
}

config_amavisd()
{
    ECHO_INFO "Create directories for amavisd-new: /var/amavisd/{tmp,var,db}."
    mkdir /var/amavisd/{tmp,var,db}
    chown -R _clamav:_clamav /var/amavisd/

    ECHO_INFO "Backup old configuration file ${AMAVISD_CONF} to ${AMAVISD_CONF}.${TIME}."
    cp ${AMAVISD_CONF} ${AMAVISD_CONF}.${TIME}

    # Configure /etc/amavisd.conf.
    ECHO_INFO "Configure amavisd-new: ${AMAVISD_CONF}."
    perl -pi -e 's/^(\$max_servers)/$1\ =\ 15\;\t#/' ${AMAVISD_CONF}
    perl -pi -e 's/^(\$daemon_user)/$1\ =\ "_clamav"\;\t#/' ${AMAVISD_CONF}
    perl -pi -e 's/^(\$daemon_group)/$1\ =\ "_clamav"\;\t#/' ${AMAVISD_CONF}

    export HOSTNAME="$(hostname)"
    perl -pi -e 's/^(\$mydomain)/$1\ =\ \"$ENV{'HOSTNAME'}\"\;\t#/' ${AMAVISD_CONF}

    # Set default score.
    #perl -pi -e 's/(.*)(sa_tag_level_deflt)(.*)/${1}${2} = 4.0; #${3}/' ${AMAVISD_CONF}
    #perl -pi -e 's/(.*)(sa_tag2_level_deflt)(.*)/${1}${2} = 6; #${3}/' ${AMAVISD_CONF}
    #perl -pi -e 's/(.*)(sa_kill_level_deflt)(.*)/${1}${2} = 10; #${3}/' ${AMAVISD_CONF}

    # Remove the content from '@av_scanners' to the end of file.
    NEW_CONF="$(sed '/\@av_scanners/,$d' ${AMAVISD_CONF})"

    # Generate new configration file(Part).
    echo -e "${NEW_CONF}" > ${AMAVISD_CONF}

    # Set pid_file.
    echo '$pid_file = "/var/run/amavisd.pid";' >> ${AMAVISD_CONF}

    # Set listen IP/PORT.
    cat >> ${AMAVISD_CONF} <<EOF
\$notify_method  = 'smtp:[127.0.0.1]:10025';
\$forward_method = 'smtp:[127.0.0.1]:10025';

EOF

    # Set default action.
    cat >> ${AMAVISD_CONF} <<EOF
\$final_virus_destiny      = D_DISCARD;
\$final_banned_destiny     = D_PASS;
\$final_spam_destiny       = D_PASS;
\$final_bad_header_destiny = D_PASS;

EOF

    cat >> ${AMAVISD_CONF} <<EOF
@av_scanners = (

    #### http://www.clamav.net/
    ['ClamAV-clamd',
    \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd"],
    qr/\bOK$/, qr/\bFOUND$/,
    qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
);

@av_scanners_backup = (

    ### http://www.clamav.net/   - backs up clamd or Mail::ClamAV
    ['ClamAV-clamscan', 'clamscan',
    "--stdout --disable-summary -r --tempdir=$TEMPBASE {}", [0], [1],
    qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
);

# SpamAssassin debugging. Default if off(0).
\$sa_debug = 0;
\$sa_spam_modifies_subj = 1;

1;  # insure a defined return
EOF
    # ------------- END configure /etc/amavisd.conf ------------

    # Configure postfix: master.cf.
    cat >> ${POSTFIX_FILE_MASTER_CF} <<EOF
smtp-amavis unix -	-	-	-	2  smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20

127.0.0.1:10025 inet n	-	-	-	-  smtpd
    -o content_filter=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o mynetworks_style=host
    -o mynetworks=127.0.0.0/8
    -o strict_rfc821_envelopes=yes
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
EOF

    postconf -e 'content_filter=smtp-amavis:[127.0.0.1]:10024'
}

add_rc_entry_for_amavisd()
{
    ECHO_INFO "Add RC entry for amavisd-new."
    echo "amavisd_flags=''" >> ${RC_CONF_LOCAL}

    cat >> ${RC_LOCAL} <<EOF
# Start amavisd-new.
if [ X"\${amavisd_flags}" != X"NO" ]; then
    echo -n ' amavisd'
    /usr/local/sbin/amavisd \${amavisd_flags} 
fi
EOF
}

# --------------------------------------------------
# For spamd(8) and PF.
# --------------------------------------------------
add_rc_entry_for_spamd()
{
    ECHO_INFO "Add RC entry for spamd."
    
    #
    # Check spamd(8) for details.
    #
    # We lie to client we use 'sendmail'   -> '-n Sendmail'
    # Bind to '127.0.0.1' by default    -> '-l 127.0.0.1'
    #
    echo 'spamd_flags="-v -S 40 -n Sendmail -h 127.0.0.1 -l 127.0.0.1 -G 1:4:864"' >>${RC_CONF_LOCAL}
}

config_spamd()
{
    ECHO_INFO "Backup default spamd.conf: ${SPAMD_CONF} -> ${SPAMD_CONF}.${TIME}."
    cp ${SPAMD_CONF} ${SPAMD_CONF}.${TIME}

    ECHO_INFO "Generate new configuration file: ${SPAMD_CONF}."
    cat > ${SPAMD_CONF} <<EOF
${CONF_MSG}
all:\\
    ::
#    :whitelist:blacklist:

#whitelist:\\
#    :white:\\
#    :method=file:\\
#    :file=${MAIL_WHITELIST}:

#blacklist:\\
#    :black:\\
#    :method=file:\\
#    :file=${MAIL_BLACKLIST}:
EOF

    ECHO_INFO "Enable spamd-setup in crontab."
    perl -pi -e 's/^(#)(.*)(spamd-setup)/${2}${3}/' /var/cron/tabs/root
}

add_rc_entry_for_pf()
{
    ECHO_INFO "Add RC entry for PF."
    cat >> ${RC_CONF_LOCAL} <<EOF
pf=YES
pf_rules=/etc/pf.conf
EOF
}

config_pf()
{
    ECHO_INFO "Backup orig rule file /etc/pf.conf to /etc/pf.conf.$TIME."
    cp /etc/pf.conf /etc/pf.conf.${TIME}

    ECHO_INFO "Generate new pf rule file."
    cat > /etc/pf.conf <<EOF
${CONF_MSG}
#
# Macros.
#

ext_if="pcn0"
lo_if="lo0"

#
# Define tables.
#

table <spamd> persist
table <spamd-white> persist

#
# Custom tables for mail service.
#

table <mail-whitelist> persist file "${MAIL_WHITELIST}"
table <mail-blacklist> persist file "${MAIL_BLACKLIST}"

#
# pass: <spamd-white>, <mail-whitelist>
# rdr:  <spamd>, !<mail-blacklist>
#

# ---- mail from: \$lo_if ----
no rdr inet proto tcp from \$lo_if to any port smtp

# ---- whitelist ----
no rdr inet proto tcp from <mail-whitelist> to any port smtp
no rdr inet proto tcp from <spamd-white> to any port smtp

# ---- grey list ----
# Add 'log' after 'pass' for debug.
#
rdr pass inet proto tcp from <spamd> to any port smtp -> \$lo_if port spamd
rdr pass inet proto tcp from !<mail-blacklist> to any port smtp -> \$lo_if port spamd

#
# Default strategy.
#

#block in on \$ext_if

#
# Block mail blacklist.
# Add 'log' before 'quick' for debug.
#

block in quick on \$ext_if proto tcp from <mail-blacklist> to any port smtp

#
# Open services.
#

pass in quick on \$ext_if proto tcp from any to \$ext_if \
    port { ssh imap imaps www https pop3 } keep state

#
# For DNS service.
#

pass out quick on \$ext_if proto udp from \$ext_if to any port domain keep state
EOF
}

# -------------------------------------------------
# Enable mailgraph.
# -------------------------------------------------
install_mailgraph()
{
    install_pkg mailgraph PORT_MAILGRAPH
}

config_mailgraph()
{
    ECHO_INFO "Configure mailgraph."

    sh ${ROOTDIR}/tools/rrdtool_in_chrooted_httpd.sh
    sh ${ROOTDIR}/tools/perl_in_chrooted_httpd.sh

    cp /usr/local/lib/mailgraph/mailgraph.cgi ${HTTPD_SERVERROOT}/cgi-bin/
    chmod +x ${HTTPD_SERVERROOT}/cgi-bin/mailgraph.cgi
}

add_rc_entry_for_mailgraph()
{
    ECHO_INFO "Add rc entry for mailgraph."

    cat >> ${RC_CONF_LOCAL} <<EOF
mailgraph_flags="${MAILGRAPH_FLAGS}"
EOF

    cat >> ${RC_LOCAL} <<EOF
# Start mailgraph.
if [ X"\${mailgraph_flags}" != X"NO" ]; then
    echo -n ' mailgraph'
    /usr/local/bin/mailgraph \${mailgraph_flags}
fi
EOF
}

# ***************************************************************************
# ****************************** Script Main ********************************
# ***************************************************************************

# Start installation.
echo -en "\nStart installation now? [Y|n]"
read ANSWER

case ${ANSWER} in
    N|n )
        ECHO_INFO "Exit."
        exit 255
        ;;
    Y|y|* )
        :
        ;;
esac

# Do *NOT* comment this line.
perl -pi -e "s/^echo\ \'\.\'//" ${RC_LOCAL}

# *****************************************
# For Apache and PHP5(with extensions).
# *****************************************
config_httpd && \
add_rc_entry_for_httpd && \
install_php5_core && \
install_php_extension && \
generate_php_info_page && \
start_httpd

# *****************************************
# For OpenLDAP, LDAP schemas, phpLDAPadmin.
# *****************************************
install_openldap_server && \
install_openldap_qmail_schema && \
generate_smtpd_conf && \
generate_slapd_conf && \
generate_ldap_conf && \
setting_openldap_log && \
prepare_ldap_data_directory && \
add_rc_entry_for_openldap && \
start_openldap && \
init_ldap_tree

# *****************************************
# For phpLDAPadmin
# *****************************************
install_phpldapadmin && \
config_phpldapadmin

# *****************************************
# For cyrus-sasl-ldap.
# *****************************************
install_cyrus_sasl_ldap &&\
generate_smtpd_conf && \
generate_saslauthd_conf && \
add_rc_entry_for_saslauthd

# *****************************************
# For Postfix.
# *****************************************
install_postfix && \
enable_postfix && \
basic_postfix_config && \
add_user_group_vmail && \
maildrop_config && \
ldap_config_for_postfix && \
sasl_config_for_postfix

# ****************************************
# For Courier authlib-ldap/pop3/imap.
# ****************************************
install_courier_authlib_ldap && \
add_rc_entry_for_authdaemon && \
ldap_config_for_courier_authlib_authdaemonrc && \
ldap_config_for_courier_authlib_authldaprc && \
install_courier_pop3 && \
add_rc_entry_for_courier_pop3 && \
install_courier_imap && \
create_user_maildir && \
add_rc_entry_for_courier_imap

# ****************************************
# For SquirrelMail and plugin(s).
# ****************************************
prepare_env_for_squirrelmail && \
config_squirrelmail

# *********
# For SquirrelMail Translations.
# *********
config_squirrelmail_translations && \
convert_translation_locale 'zh_CN' 'zh_CN.GB2312' 'zh_CN.UTF8' 'gb2312' 'utf-8'
convert_translation_locale 'zh_TW' 'zh_CN.BIG5' 'zh_CN.UTF8' 'big5' 'utf-8'

# *********
# For SquirrelMail Plugins
# *********
# change_ldappass
prepare_env_for_squirrelmail_plugin_change_ldappass && \
config_squirrelmail_plugin_change_ldappass

# compatibility
prepare_env_for_squirrelmail_plugin_compatibility

# Check Quota.
prepare_env_for_squirrelmail_plugin_check_quota && \
config_squirrelmail_plugin_check_quota

# Select Language.
prepare_env_for_squirrelmail_plugin_select_language

# Enable all defined plugins.
enable_squirrelmail_plugins ${ENABLED_PLUGINS}

# ****************************************
# For SpamAssassin
# ****************************************
install_spamassassin && \
config_spamassassin

# ****************************************
# For ClamAV
# ****************************************
install_unrar_unarj && \
install_clamav && \
config_clamav_freshclam && \
add_rc_entry_for_freshclam && \
config_clamav_clamd && \
add_rc_entry_for_clamd

# ****************************************
# For amavisd-new 
# ****************************************
install_amavisd && \
config_amavisd && \
add_rc_entry_for_amavisd

# ****************************************
# For spamd(8) and PF
# ****************************************
add_rc_entry_for_spamd && \
config_spamd && \
add_rc_entry_for_pf && \
config_pf

# ****************************************
# For mailgraph.
# ****************************************
install_mailgraph && \
config_mailgraph && \
add_rc_entry_for_mailgraph

# Do *NOT* comment the following line.
echo "echo '.'" >>${RC_LOCAL}

cat <<EOF
===========================================================================
**** Congratulations! Installation/Configuration Completed.            ****
**** ----------------------------------------------------------------- ****
**** Please modify the 'ext_if' to fit your need in /etc/pf.conf.      ****
===========================================================================
EOF

# Some useful tools.
echo -n "Would you like to run freshclam now? [Y|n]"
read ANSWER
case $ANSWER in
    N|n ) ECHO_INFO "Skip freshclam." ;;
    Y|y|* ) freshclam ;;
esac

